﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;

using Outcoder;
using Outcoder.ComponentModel;
using Outcoder.Messaging;
using Outcoder.Services;
using Outcoder.UserOptionsModel;
using Outcoder.UserOptionsModel.UserOptions;

namespace CalciumTemplateApp
{
	public partial class AppSettings : ObservableObject, 
		IMessageSubscriber<SettingChangeEventArgs>
	{
		readonly ISettingsService settingsService = Dependency.Resolve<ISettingsService>();
		static bool userOptionsInitialized;

		internal void Initialize()
		{
			if (userOptionsInitialized)
			{
				return;
			}
			userOptionsInitialized = true;

			if (FirstRunDate == DateTimeOffset.MinValue)
			{
				FirstRun = true;
				FirstRunDate = DateTimeOffset.Now;
			}

			var userOptionsService = Dependency.Resolve<IUserOptionsService>();
			OptionCategory defaultCategory = new OptionCategory(
							"General", () => AppResources.OptionCategories_General);

			/* Add options to the following collection and they will be 
			 * automatically displayed on the options page. 
			 * Each UserOption object must have a unique key. 
			 * Lambda expression are used for most of the properties 
			 * to allow your app to switch languages without requiring a restart. 
			 * You can specify a template for the option by setting its TemplateFunc property.
			 * See the UserOptionBase implementations. */
			List<IUserOption> generalOptions = new List<IUserOption>
			        {
						new BooleanUserOption(() => AppResources.Options_ExampleOption1_Title, ExampleOption1Key, () => exampleOption1DefaultValue),
						new StringUserOption(() => AppResources.Options_ExampleOption2_Title, ExampleOption2Key, () => exampleOption2DefaultValue),
					};

			userOptionsService.Register(generalOptions, defaultCategory);
		}

		public const string FirstRunDateKey = "FirstRunDate";
		static readonly DateTimeOffset firstRunDateDefaultValue = DateTimeOffset.MinValue;

		public DateTimeOffset FirstRunDate
		{
			get
			{
				return settingsService.GetSetting(FirstRunDateKey, firstRunDateDefaultValue);
			}
			private set
			{
				settingsService.SetSetting(FirstRunDateKey, value);
			}
		}

		bool firstRun;

		public bool FirstRun
		{
			get
			{
				return firstRun;
			}
			private set
			{
				firstRun = value;
			}
		}

		/// <summary>
		/// Receives the settings changed message from the message bus.
		/// We signal that the setting has changed by using the convention 
		/// that the property name is the setting name.
		/// </summary>
		/// <param name="message">The <see cref="DanielVaughan.Services.SettingChangeEventArgs"/> 
		/// instance containing the event data.</param>
		async Task IMessageSubscriber<SettingChangeEventArgs>.ReceiveMessage(SettingChangeEventArgs message)
		{
			OnPropertyChanged(message.SettingName);
		}

		public const string ExampleOption1Key = "ExampleOption1";
		static bool exampleOption1DefaultValue = false;

		public bool ExampleOption1
		{
			get
			{
				return settingsService.GetSetting(ExampleOption1Key, exampleOption1DefaultValue);
			}
			private set
			{
				settingsService.SetSetting(ExampleOption1Key, value);
			}
		}

		public const string ExampleOption2Key = "ExampleOption2";
		static string exampleOption2DefaultValue = string.Empty;

		public string ExampleOption2
		{
			get
			{
				return settingsService.GetSetting(ExampleOption2Key, exampleOption2DefaultValue);
			}
			private set
			{
				settingsService.SetSetting(ExampleOption2Key, value);
			}
		}

		#region Singleton implementation

		static readonly AppSettings instance = new AppSettings();

		AppSettings()
		{
			var messageBus = Dependency.Resolve<IMessenger>();
			messageBus.Subscribe(this);
		}

		public static AppSettings Instance
		{
			get
			{
				return instance;
			}
		}

		#endregion
	}
}
